#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
CSV to JSON 转换器
支持将CSV文件转换为多种JSON格式
"""

import pandas as pd
import json
import os
import argparse
from datetime import datetime
from pathlib import Path

# 尝试导入colorama进行彩色输出
try:
    from colorama import init, Fore, Style
    init()
    HAS_COLOR = True
except ImportError:
    HAS_COLOR = False
    Fore = Style = type('MockColor', (), {'RED': '', 'GREEN': '', 'YELLOW': '', 'BLUE': '', 'RESET_ALL': ''})()

def print_colored(text, color=None):
    """打印彩色文本"""
    if HAS_COLOR and color:
        print(f"{color}{text}{Style.RESET_ALL}")
    else:
        print(text)

def safe_json_convert(obj):
    """安全地转换对象为JSON可序列化格式"""
    if pd.isna(obj):
        return None
    elif isinstance(obj, (pd.Timestamp, datetime)):
        return obj.isoformat()
    elif isinstance(obj, (int, float)) and pd.isna(obj):
        return None
    else:
        return obj

def convert_csv_to_json(csv_file, output_dir="job_info", generate_all=True, 
                       generate_complete=False, generate_separate=False, 
                       generate_metadata=False, indent=2, generate_readme=True,
                       encoding='utf-8'):
    """
    将CSV文件转换为JSON格式
    
    Args:
        csv_file: CSV文件路径
        output_dir: 输出目录
        generate_all: 是否生成所有格式
        generate_complete: 是否生成完整数据文件
        generate_separate: 是否生成单独职位文件
        generate_metadata: 是否生成带元数据文件
        indent: JSON缩进空格数
        generate_readme: 是否生成README文件
        encoding: CSV文件编码
    """
    
    # 检查CSV文件是否存在
    if not os.path.exists(csv_file):
        print_colored(f"❌ 错误: CSV文件 '{csv_file}' 不存在", Fore.RED)
        return False
    
    try:
        print_colored(f"📖 正在读取CSV文件: {csv_file}", Fore.BLUE)
        
        # 尝试不同的编码读取CSV文件
        encodings_to_try = [encoding, 'utf-8', 'gbk', 'utf-8-sig', 'gb2312']
        df = None
        used_encoding = None
        
        for enc in encodings_to_try:
            try:
                df = pd.read_csv(csv_file, encoding=enc)
                used_encoding = enc
                print_colored(f"✅ 成功使用 {enc} 编码读取文件", Fore.GREEN)
                break
            except UnicodeDecodeError:
                continue
            except Exception as e:
                print_colored(f"⚠️ 使用 {enc} 编码时出错: {e}", Fore.YELLOW)
                continue
        
        if df is None:
            print_colored("❌ 无法读取CSV文件，请检查文件编码", Fore.RED)
            return False
        
        print_colored(f"📊 读取到 {len(df)} 行数据，{len(df.columns)} 列", Fore.GREEN)
        print_colored(f"列名: {', '.join(df.columns.tolist())}", Fore.BLUE)
        
        # 创建输出目录
        os.makedirs(output_dir, exist_ok=True)
        print_colored(f"📁 输出目录: {output_dir}", Fore.BLUE)
        
        # 数据预处理
        print_colored("🔄 正在处理数据...", Fore.YELLOW)
        
        # 转换数据为JSON可序列化格式
        df_clean = df.map(safe_json_convert)
        
        # 确定要生成的文件类型
        if generate_all:
            generate_complete = generate_separate = generate_metadata = True
        
        generated_files = []
        
        # 1. 生成完整数据文件
        if generate_complete:
            print_colored("📝 生成完整数据文件...", Fore.YELLOW)
            complete_data = df_clean.to_dict('records')
            
            complete_file = os.path.join(output_dir, 'job_data.json')
            with open(complete_file, 'w', encoding='utf-8') as f:
                json.dump(complete_data, f, ensure_ascii=False, indent=indent)
            
            generated_files.append(('job_data.json', '完整职位数据'))
            print_colored(f"✅ 完整数据文件已生成: {complete_file}", Fore.GREEN)
        
        # 2. 生成单独职位文件
        if generate_separate:
            print_colored("📝 生成单独职位文件...", Fore.YELLOW)
            for idx, row in df_clean.iterrows():
                job_data = row.to_dict()
                job_file = os.path.join(output_dir, f'job_{idx}.json')
                
                with open(job_file, 'w', encoding='utf-8') as f:
                    json.dump(job_data, f, ensure_ascii=False, indent=indent)
            
            generated_files.append((f'job_0.json ~ job_{len(df)-1}.json', '单独职位数据文件'))
            print_colored(f"✅ 已生成 {len(df)} 个单独职位文件", Fore.GREEN)
        
        # 3. 生成带元数据的文件
        if generate_metadata:
            print_colored("📝 生成带元数据文件...", Fore.YELLOW)
            metadata = {
                "conversion_time": datetime.now().isoformat(),
                "source_file": os.path.basename(csv_file),
                "source_encoding": used_encoding,
                "total_records": len(df),
                "columns": df.columns.tolist(),
                "data": df_clean.to_dict('records')
            }
            
            metadata_file = os.path.join(output_dir, 'job_data_with_metadata.json')
            with open(metadata_file, 'w', encoding='utf-8') as f:
                json.dump(metadata, f, ensure_ascii=False, indent=indent)
            
            generated_files.append(('job_data_with_metadata.json', '带元数据的完整数据'))
            print_colored(f"✅ 带元数据文件已生成: {metadata_file}", Fore.GREEN)
        
        # 4. 生成README文件
        if generate_readme:
            print_colored("📝 生成README文件...", Fore.YELLOW)
            readme_content = f"""# 职位数据 JSON 文件

## 文件说明

本目录包含从CSV文件转换而来的职位数据，以下是各文件的说明：

"""
            
            for filename, description in generated_files:
                readme_content += f"- **{filename}**: {description}\n"
            
            readme_content += f"""
## 数据统计

- **数据来源**: {os.path.basename(csv_file)}
- **源文件编码**: {used_encoding}
- **转换时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
- **职位总数**: {len(df)}
- **数据列数**: {len(df.columns)}

## 数据结构

数据包含以下字段：
"""
            
            for col in df.columns:
                readme_content += f"- `{col}`: {df[col].dtype}\n"
            
            readme_content += f"""

## 使用说明

1. `job_data.json` 包含所有职位数据的数组格式
2. `job_X.json` 文件包含单个职位的详细信息（X为职位索引）
3. `job_data_with_metadata.json` 包含数据和转换元信息
4. 如需要处理单个职位，使用对应的 `job_X.json` 文件

## 重新生成数据

### 命令行模式
转换脚本支持多种命令行选项：

```bash
# 生成所有格式文件
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -a

# 只生成完整数据文件
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -c

# 只生成单独职位文件  
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -s

# 只生成带元数据文件
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -m

# 自定义输出目录和编码
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -o custom_output --encoding gbk

# 不生成README文件，使用4个空格缩进
python convert_csv_to_json.py -f {os.path.basename(csv_file)} -c --no-readme --indent 4
```

### 交互式模式
直接运行脚本进入交互式模式：
```bash
python convert_csv_to_json.py
```

### 查看所有选项
```bash
python convert_csv_to_json.py --help
```
"""
            
            readme_file = os.path.join(output_dir, 'README.md')
            with open(readme_file, 'w', encoding='utf-8') as f:
                f.write(readme_content)
            
            print_colored(f"✅ README文件已生成: {readme_file}", Fore.GREEN)
        
        print_colored(f"\n🎉 转换完成！共生成 {len(generated_files)} 种类型的文件", Fore.GREEN)
        print_colored(f"📁 输出目录: {os.path.abspath(output_dir)}", Fore.BLUE)
        
        return True
        
    except Exception as e:
        print_colored(f"❌ 转换过程中出现错误: {e}", Fore.RED)
        return False

def interactive_mode():
    """交互式模式"""
    print_colored("\n🚀 CSV to JSON 转换器 - 交互式模式", Fore.BLUE)
    print_colored("=" * 50, Fore.BLUE)
    
    # 获取CSV文件路径
    while True:
        csv_file = input("\n请输入CSV文件路径: ").strip().strip('"')
        if os.path.exists(csv_file):
            break
        else:
            print_colored(f"❌ 文件不存在: {csv_file}", Fore.RED)
            print("请检查路径是否正确，支持相对路径和绝对路径")
    
    # 获取输出目录
    default_output = "job_info"
    output_dir = input(f"\n输出目录 (默认: {default_output}): ").strip() or default_output
    
    # 获取编码
    print("\n支持的编码格式:")
    print("1. utf-8 (默认)")
    print("2. gbk")
    print("3. gb2312")
    print("4. utf-8-sig")
    print("5. 自定义")
    
    encoding_choice = input("\n请选择编码 (1-5, 默认: 1): ").strip() or "1"
    encoding_map = {
        "1": "utf-8",
        "2": "gbk", 
        "3": "gb2312",
        "4": "utf-8-sig",
        "5": input("请输入自定义编码: ").strip()
    }
    encoding = encoding_map.get(encoding_choice, "utf-8")
    
    # 选择生成类型
    print("\n选择要生成的文件类型:")
    print("1. 所有类型 (推荐)")
    print("2. 仅完整数据文件")
    print("3. 仅单独职位文件")
    print("4. 仅带元数据文件")
    print("5. 自定义组合")
    
    type_choice = input("\n请选择 (1-5, 默认: 1): ").strip() or "1"
    
    generate_all = generate_complete = generate_separate = generate_metadata = False
    
    if type_choice == "1":
        generate_all = True
    elif type_choice == "2":
        generate_complete = True
    elif type_choice == "3":
        generate_separate = True
    elif type_choice == "4":
        generate_metadata = True
    elif type_choice == "5":
        print("\n自定义组合:")
        generate_complete = input("生成完整数据文件? (y/N): ").lower().startswith('y')
        generate_separate = input("生成单独职位文件? (y/N): ").lower().startswith('y')
        generate_metadata = input("生成带元数据文件? (y/N): ").lower().startswith('y')
    
    # 其他选项
    indent_str = input("\nJSON缩进空格数 (默认: 2): ").strip() or "2"
    try:
        indent = int(indent_str)
    except ValueError:
        indent = 2
        print_colored(f"⚠️ 无效的缩进数量，使用默认值: {indent}", Fore.YELLOW)
    
    generate_readme = not input("跳过生成README文件? (y/N): ").lower().startswith('y')
    
    # 确认信息
    print_colored("\n📋 转换配置:", Fore.BLUE)
    print(f"CSV文件: {csv_file}")
    print(f"输出目录: {output_dir}")
    print(f"文件编码: {encoding}")
    print(f"JSON缩进: {indent}")
    print(f"生成README: {'是' if generate_readme else '否'}")
    
    if input("\n确认开始转换? (Y/n): ").lower() not in ['n', 'no']:
        return convert_csv_to_json(
            csv_file=csv_file,
            output_dir=output_dir,
            generate_all=generate_all,
            generate_complete=generate_complete,
            generate_separate=generate_separate,
            generate_metadata=generate_metadata,
            indent=indent,
            generate_readme=generate_readme,
            encoding=encoding
        )
    else:
        print_colored("❌ 转换已取消", Fore.YELLOW)
        return False

def main():
    parser = argparse.ArgumentParser(
        description='CSV to JSON 转换器 - 将CSV文件转换为多种JSON格式',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
使用示例:
  %(prog)s                           # 交互式模式
  %(prog)s -f data.csv -a            # 生成所有格式文件
  %(prog)s -f data.csv -c            # 只生成完整数据文件  
  %(prog)s -f data.csv -s            # 只生成单独职位文件
  %(prog)s -f data.csv -m            # 只生成带元数据文件
  %(prog)s -f data.csv -o output --encoding gbk  # 自定义输出和编码
        """
    )
    
    parser.add_argument('-f', '--file', 
                       help='CSV源文件路径')
    
    parser.add_argument('-o', '--output', 
                       default='job_info',
                       help='输出目录 (默认: job_info)')
    
    parser.add_argument('--encoding',
                       default='utf-8',
                       help='CSV文件编码 (默认: utf-8)')
    
    # 输出类型选项
    output_group = parser.add_mutually_exclusive_group()
    output_group.add_argument('-a', '--all',
                             action='store_true',
                             help='生成所有格式文件 (默认)')
    
    output_group.add_argument('-c', '--complete',
                             action='store_true', 
                             help='只生成完整数据文件')
    
    output_group.add_argument('-s', '--separate',
                             action='store_true',
                             help='只生成单独职位文件')
    
    output_group.add_argument('-m', '--metadata',
                             action='store_true',
                             help='只生成带元数据文件')
    
    parser.add_argument('--indent',
                       type=int,
                       default=2,
                       help='JSON缩进空格数 (默认: 2)')
    
    parser.add_argument('--no-readme',
                       action='store_true',
                       help='不生成README文件')
    
    args = parser.parse_args()
    
    # 如果没有指定文件，进入交互模式
    if not args.file:
        return interactive_mode()
    
    # 检查输出类型，默认生成所有文件
    if not any([args.complete, args.separate, args.metadata]):
        args.all = True
    
    # 执行转换
    success = convert_csv_to_json(
        csv_file=args.file,
        output_dir=args.output,
        generate_all=args.all,
        generate_complete=args.complete,
        generate_separate=args.separate,
        generate_metadata=args.metadata,
        indent=args.indent,
        generate_readme=not args.no_readme,
        encoding=args.encoding
    )
    
    if success:
        print_colored("\n✨ 所有操作完成！", Fore.GREEN)
    else:
        print_colored("\n❌ 转换失败！", Fore.RED)
        return 1
    
    return 0

if __name__ == "__main__":
    exit(main()) 